using Godot;
using PlayerState;
using System;
using System.Reflection;

public partial class Player : CharacterBody2D
{
	[Export]
	public int Health =5,Damage = 4;
	
	[Export]
	public bool FacingLeft = false;

	public Color CurrentColor;
    public Color OriginColor;

	public AnimatedSprite2D AnimaPlayer;

	public const float Speed = 300.0f;
	public const float JumpVelocity = -400.0f;

	public bool IsRoll=false,
		CanRoll=true,
		IsAttack=false,
		CanAttack=true;

	public Timer Invincible;
	public Timer Blink;
	public bool IsBlink = false;	
	
	public Vector2 ScreenSize;

	public StateMeachine stateMeachine;
	
    public override void _Ready()
    {        
		ScreenSize = GetViewportRect().Size;
		stateMeachine = new StateMeachine(GetNode<StateNode>("StateNode/Idle"));

		AnimaPlayer = GetNode<AnimatedSprite2D>("AnimaPlayer");
		AnimaPlayer.AnimationFinished+=GetNode<Roll>("StateNode/Roll").OnRollFinished;

		Invincible = GetNode<Timer>("Invincible");
		Invincible.Timeout+=ResumePlain;

		CurrentColor=Modulate;
		OriginColor=Modulate;

		Blink = GetNode<Timer>("Blink");
		Blink.Timeout+=OnBlink;

		TimeController.Instance.SetTimeScale(this,1.0f);
    }
    public override void _PhysicsProcess(double delta)
	{						
		float scale = TimeController.Instance.GetTimeScale(this);
		// Add the gravity.
		if (!IsOnFloor())
		{
			Velocity += GetGravity() * (float)delta;
		}				

		delta *=scale;

		HandleMessage((float)delta);

		Position = new Vector2(
			x:Mathf.Clamp(Position.X,0,ScreenSize.X),
			y:Mathf.Clamp(Position.Y,0,ScreenSize.Y)
		);

		stateMeachine.current.OnUpdate((float)delta);		

		MoveAndSlide();

		var animation = GetNode<AnimatedSprite2D>("AnimaPlayer");
		if(FacingLeft)
			animation.FlipH = true;
		else
			animation.FlipH = false;
									
		animation.Play();
	}

	public void HandleMessage(float delta)
	{
		Vector2 velocity = Velocity;					
	
		if(Input.IsActionPressed("ui_left"))
			velocity.X=-Speed;
		else if(Input.IsActionPressed("ui_right"))
			velocity.X=Speed;
		else
			velocity.X = Mathf.MoveToward(Velocity.X, 0, Speed);
		if(Input.IsActionPressed("ui_left")&&Input.IsActionPressed("ui_right"))
			velocity.X=Mathf.MoveToward(Velocity.X, 0, Speed);

		if(Input.IsActionJustPressed("ui_accept") && IsOnFloor())
		{			
			velocity.Y=JumpVelocity;
			SwitchTo("Jump");
		}

		if(Input.IsActionJustPressed("ui_down"))
			OnRoll();

		if(Input.IsMouseButtonPressed(MouseButton.Left))
			OnAttack();

		if(Input.IsMouseButtonPressed(MouseButton.Right))
			BulletTime.Instance.UseBulletTime();

		if(velocity.X>0)
			FacingLeft = false;
		else if(velocity.X<0)
			FacingLeft = true;
		
		Velocity = velocity;
	}	

	public void SwitchTo(string type)
	{
		stateMeachine.SwitchTo(GetNode<StateNode>($"StateNode/{type}"));
	}

	public void EnterInvincible()
	{	
		Invincible.Start();
						
		SetCollisionLayerValue(2,false);
	}

	public void ResumePlain()
	{
		SetCollisionLayerValue(2,true);				
		
		if(!Blink.IsStopped())
		{
			Modulate = CurrentColor;
			IsBlink = false;
			Blink.Stop();
		}					
	}
	
	public void OnHurt()
	{
		Blink.Start();
		IsBlink = true;	

		GetNode<AudioStreamPlayer2D>("HurtMusic").Play();

		Health-=1;
		EnterInvincible();
	}

	public void OnBlink()
	{				
		if(IsBlink)
			Modulate = new Color(255.0f,255.0f,255.0f,1);
		else
		{			
			Modulate = CurrentColor;
		}
		IsBlink = !IsBlink;				
	}

	public void OnRoll()
	{
		if(!IsRoll&&IsOnFloor()&&CanRoll)
			SwitchTo("Roll");
	}

	public bool IsRun()
	{						
		return Input.IsActionPressed("ui_left")^Input.IsActionPressed("ui_right")&&IsOnFloor();
	}
		
	public void OnAttack()
	{
		if(!IsAttack&&CanAttack)
			SwitchTo("Attack");
	}	
}
